<?php
abstract class Agitum_Model_Object implements Iterator, Zend_Acl_Resource_Interface
{
	protected $_data = null;
	protected $_table = null;
	protected $_info = null;
	protected $_ordered = null;
	private   $_position = 0;
	protected $_fields = null;
	protected $_name = null;
	

	public function __toString() {
		return $this->name;
	}

	public function __construct(array $options = null)
    {
        $this->init();

    	if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    public function getResourceId() {
    	return $this->id;
    }

    protected function init() 
    {
    	$this->setDbTable($this->_t_class);
    	
    	$this->_fields['id'] = array_merge($this->_fields['id'], array('label' => 'ID', 'readOnly' => true));
        $this->_fields['guid'] = array_merge($this->_fields['guid'], array('label' => 'Имя', 'readOnly' => false));
    	$this->_fields['name'] = array_merge($this->_fields['name'], array('label' => 'Имя', 'readOnly' => false));
    	$this->_fields['created'] = array_merge($this->_fields['created'], array('label' => 'Дата создания', 'readOnly' => true));
    	$this->_fields['updated'] = array_merge($this->_fields['updated'], array('label' => 'Дата изменения', 'readOnly' => true));
    	$this->_fields['relname'] = array_merge($this->_fields['relname'], array('label' => 'Имя таблицы', 'readOnly' => true));
    }

	public function rewind() {
        $this->_position = 0;
    }

    public function current() {
    	$key = $this->_ordered[$this->_position];
        return $this->$key;
    }

    public function key() {
        return $this->_ordered[$this->_position];
    }

    public function next() {
        ++$this->_position;
    }

    public function valid() {
    	if ( $this->_position == count($this->_ordered) )
    		return false;

    	$key = $this->_ordered[$this->_position];
    	$methods = get_class_methods($this);
    	
    	if ( in_array('get'.ucfirst($key), $methods) )
    		return true;
    		
        return true;
    }
    
    public function getFields() {
    	return $this->_fields;
    }
    
    public function getRelname() 
    {
    	return $this->_info['name'];
    }

    public function setDbTable($dbTable)
    {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable();
        }
        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Exception('Invalid table data gateway provided');
        }
        $info = $dbTable->info();
        $this->_info = $info;
        $this->_name = $info['name'];
        $this->_fields = $info['metadata'];
        $this->_ordered = $info['cols'];
        $this->_table = $dbTable;
        $this->relname = $info['name'];
        return $this;
    }
    
  	public function getDbTable()
    {
        return $this->_table;
    }

    public function setOptions(array $options)
	{
		foreach ($options as $key => $value) {
			$method = 'set' . ucfirst($key);
			$this->$method($value);
		}
		return $this;
	}

	public function __isset($key) {
		return isset($this->_data[$key]);
	}
	
	public function __set($name, $value) {
		$method = "set".ucfirst($name);
		$this->$method($value);
	}

	public function __get($name) {
		$method = "get".ucfirst($name);
		return $this->$method();
	}

	public function __call($name, $args) {

		$gs = substr($name, 0, 3);
		$key = strtolower(substr($name, 3));

		if ( !isset($this->_fields[$key]) ) {
			throw new Exception('Invalid property: '.$key);
		}

		if ( $gs == 'set') {
			$this->_data[$key] = $args[0];
		} else if ( $gs == 'get' ) {
			return isset($this->_data[$key]) ? $this->_data[$key] : null;
		}
    }

    public function save() 
    {
    	$data = array();
    	foreach ($this->_fields as $key => $val ) {
    	    $data[$key] = $this->$key;
    	    if ( $val['DATA_TYPE'] == 'bool') {
    	        $data[$key] = new Zend_Db_Expr($this->$key.'::boolean');
    	    } else 
    	        $data[$key] = $this->$key;
    	}
    	
    	if (!$data['name']) {
    		$tr = new Agitum_Filter_Translit();
    		$data['name'] = $tr->filter($data['name']); 
    	}
    	
    	unset($data['created']);
    	unset($data['updated']);
    	unset($data['relname']);
    	
    	$id = $this->id;
    	
        if (null === $id ) 
        {
            //unset($data['role']);
            $this->getDbTable()->insert($data);
            $this->id = $this->getDbTable()->getAdapter()->lastInsertId($this->_name, 'id');
        } 
        else { 
        	
            $this->getDbTable()->update($data, array('id = ?' => $id));
        }
            
        return $this;
    }

    public function find()
    {
    	$select = $this->getDbTable()->select();
    	foreach ( $this->_fields as $key => $val ) {
    		if ( isset($this->$key) ) {
    			$select->where($key . ' = ?', $this->$key );
    		}
    	}
		$row = $select->query()->fetch();
        if (!$row) {
            return false;
        }
        foreach ($row as $key => $value) {
        	$this->$key = $value;
        }
        return $this;
    }
    
	public function fetchMap($key = 'id')
    {
    	$rows = $this->fetchAll();
    	$data = array();
    	foreach ( $rows as $i => $row) {
    		$data[$row[$key]] = $row;
    	}
    	unset($rows);
 		return $data;
    }

 	public function fetchAll()
    {
 		return $this->getDbTable()->select()->order('id')->query()->fetchAll();
    }
}